package me.sauce.folkpocket48.data.remote.utils

import android.util.Log

import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.OutputStream

import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

object AESEncryptUtils {
    private val legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
            .toCharArray()

    @Throws(Exception::class)
    fun encrypt(sSrc: String, aesKey: String?): String {
        var aesKey=aesKey
        if (aesKey == null) {
            aesKey = ""
        }
        //判断是否为16为位
        if (aesKey.length != 16) {
            Log.d("aesKey", "aesKey长度不是16位")
        }
        val raw = aesKey.toByteArray(charset("UTF-8"))
        val keySpec = SecretKeySpec(raw, "AES")
        val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")//算法、模式、补码方式
        cipher.init(Cipher.ENCRYPT_MODE, keySpec)
        val encrypted = cipher.doFinal(sSrc.toByteArray(charset("UTF-8")))
        return encode(encrypted)

    }


    @Throws(Exception::class)
    fun decrypt(sSrc: String, aesKey: String?): String {
        var aesKey = aesKey
        if (aesKey == null) {
            aesKey = ""
        }
        //判断是否为16为位
        if (aesKey.length != 16) {
            Log.d("aesKey", "aesKey长度不是16位")
        }
        val raw = aesKey.toByteArray(charset("utf-8"))
        val keySpec = SecretKeySpec(raw, "AES")
        val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
        cipher.init(Cipher.DECRYPT_MODE, keySpec)
        val encrypted = decode(sSrc)
        val original = cipher.doFinal(encrypted)
        return String(original)
    }

    fun encode(data: ByteArray): String {
        val start = 0
        val len = data.size
        val buf = StringBuffer(data.size * 3 / 2)

        val end = len - 3
        var i = start
        var n = 0

        while (i <= end) {
            val d = (data[i].toInt() and 0x0ff shl 16
                    or (data[i + 1].toInt() and 0x0ff shl 8)
                    or (data[i + 2].toInt() and 0x0ff))

            buf.append(legalChars[d shr 18 and 63])
            buf.append(legalChars[d shr 12 and 63])
            buf.append(legalChars[d shr 6 and 63])
            buf.append(legalChars[d and 63])

            i += 3

            if (n++ >= 14) {
                n = 0
                buf.append(" ")
            }
        }

        if (i == start + len - 2) {
            val d = data[i].toInt() and 0x0ff shl 16 or (data[i + 1].toInt() and 255 shl 8)

            buf.append(legalChars[d shr 18 and 63])
            buf.append(legalChars[d shr 12 and 63])
            buf.append(legalChars[d shr 6 and 63])
            buf.append("=")
        } else if (i == start + len - 1) {
            val d = data[i].toInt() and 0x0ff shl 16

            buf.append(legalChars[d shr 18 and 63])
            buf.append(legalChars[d shr 12 and 63])
            buf.append("==")
        }

        return buf.toString()
    }

    private fun decode(c: Char): Int {
        return if (c in 'A'..'Z')
            c.toInt() - 65
        else if (c in 'a'..'z')
            c.toInt() - 97 + 26
        else if (c in '0'..'9')
            c.toInt() - 48 + 26 + 26
        else
            when (c) {
                '+' -> 62
                '/' -> 63
                '=' -> 0
                else -> throw RuntimeException("unexpected code: " + c)
            }
    }

    fun decode(s: String): ByteArray {

        val bos = ByteArrayOutputStream()
        try {
            decode(s, bos)
        } catch (e: IOException) {
            throw RuntimeException()
        }

        val decodedBytes = bos.toByteArray()
        try {
            bos.close()
        } catch (ex: IOException) {
            System.err.println("Error while decoding BASE64: " + ex.toString())
        }

        return decodedBytes
    }

    @Throws(IOException::class)
    private fun decode(s: String, os: OutputStream) {
        var i = 0

        val len = s.length

        while (true) {
            while (i < len && s[i] <= ' ')
                i++

            if (i == len)
                break

            val tri = ((decode(s[i]) shl 18)
                    + (decode(s[i + 1]) shl 12)
                    + (decode(s[i + 2]) shl 6)
                    + decode(s[i + 3]))

            os.write(tri shr 16 and 255)
            if (s[i + 2] == '=')
                break
            os.write(tri shr 8 and 255)
            if (s[i + 3] == '=')
                break
            os.write(tri and 255)

            i += 4
        }
    }
}

